#ifndef __IM_OBJECT_ARRAY_H__
#define __IM_OBJECT_ARRAY_H__

#include <im_base_types.h>
#include <im_object.h>

/**
 * @defgroup IMObjectArray
 * @ingroup PrivateIMBusIME
 * @{
 */

/** @struct IMObjectArray
 *  @brief An array to hold one or more objects.
 *
 * This class is a container which can hold one or more objects.
 */

IM_BEGIN_DECLS

#define IM_OBJECT_ARRAY(p)           (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_OBJECT_ARRAY,IMObjectArray))
#define IM_CONST_OBJECT_ARRAY(p)     (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_OBJECT_ARRAY,IMObjectArray))
#define IM_OBJECT_ARRAY_CLASS(c)     (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_OBJECT_ARRAY,IMObjectArrayClass))
#define IM_IS_OBJECT_ARRAY(p)        (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_OBJECT_ARRAY))
#define IM_IS_OBJECT_ARRAY_CLASS(c)  (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_OBJECT_ARRAY))
#define IM_OBJECT_ARRAY_GET_CLASS(p) (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_OBJECT_ARRAY,IMObjectArrayClass))

typedef struct _IMObjectArray        IMObjectArray;
typedef struct _IMObjectArrayClass   IMObjectArrayClass;

/**
 * @brief Create a new IMObjectArray object.
 */
IMObjectArray*  im_object_array_new             ();
/**
 * @brief Clear an IMObjectArray object.
 *
 * All objects in it will be unreferenced.
 */
void            im_object_array_clear           (IMObjectArray          *array);
/**
 * @brief Reserve a specific amount of space,
 *        to prevent reallocation when inserting many
 *        items.
 */
void            im_object_array_reserve         (IMObjectArray          *array,
                                                 IMSize                  space);
/**
 * @brief Free unused memory occupied by an IMObjectArray object.
 */
void            im_object_array_free_unused_memory (IMObjectArray       *array);
/**
 * @brief Get number of objects stored in an IMObjectArray object.
 */
IMSize          im_object_array_size            (const IMObjectArray    *array);
/**
 * @brief Get a specific object in an IMObjectArray object by its index.
 */
IMPointer       im_object_array_get             (const IMObjectArray    *array,
                                                 IMSize                  index);
/**
 * @brief Set the object in an IMObjectArray object at specified index
 *        to a new object.
 */
void            im_object_array_set             (IMObjectArray          *array,
                                                 IMSize                  index,
                                                 IMPointer               object);
/**
 * @brief Prepend an object into an IMObjectArray object.
 */
IMObjectArray*  im_object_array_prepend         (IMObjectArray          *array,
                                                 IMPointer               object);
/**
 * @brief Append an object into an IMObjectArray object.
 */
IMObjectArray*  im_object_array_append          (IMObjectArray          *array,
                                                 IMPointer               object);
/**
 * @brief Insert an object into the specific position in an IMObjectArray object.
 */
IMObjectArray*  im_object_array_insert          (IMObjectArray          *array,
                                                 IMSize                  index,
                                                 IMPointer               object);
/**
 * @brief Remove the object at specific position in an IMObjectArray object.
 */
IMObjectArray*  im_object_array_remove          (IMObjectArray          *array,
                                                 IMSize                  index);
/**
 * @brief Fast remove the object at specific position in an IMObjectArray object.
 *
 * The order of objects in the array will be changed.
 */
IMObjectArray*  im_object_array_remove_fast     (IMObjectArray          *array,
                                                 IMSize                  index);
/**
 * @brief Sort all objects in an IMObjectArray object by using specific
 *        compare function.
 */
void            im_object_array_sort            (IMObjectArray          *array,
                                                 IMCompareFunc           compare_func);
/**
 * @brief Sort all objects in an IMObjectArray object by using specific
 *        compare function with user_data.
 */
void            im_object_array_sort_with_data  (IMObjectArray          *array,
                                                 IMCompareDataFunc       compare_func,
                                                 IMPointer               user_data);
/**
 * @brief Finds the first position in which a given object could be inserted
 *        without changing the ordering.
 *
 * @return An index to the first object "not less than" obj, or array size
 *         if every object is less than obj.
 */
IMSize          im_object_array_lower_bound     (const IMObjectArray    *array,
                                                 IMPointer               obj,
                                                 IMCompareFunc           compare_func);
/**
 * @brief Finds the first position in which a given object could be inserted
 *        without changing the ordering.
 *
 * @return An index to the first object "not less than" obj, or array size
 *         if every object is less than obj.
 */
IMSize          im_object_array_lower_bound_with_data   (const IMObjectArray    *array,
                                                         IMPointer               obj,
                                                         IMCompareDataFunc       compare_func,
                                                         IMPointer               user_data);
/**
 * @brief Finds the last position in which a given object could be inserted
 *        without changing the ordering.
 *
 * @return An index to the first object greater than obj, or array size
 *         if no objects are greater than obj.
 */
IMSize          im_object_array_upper_bound     (const IMObjectArray    *array,
                                                 IMPointer               obj,
                                                 IMCompareFunc           compare_func);
/**
 * @brief Finds the last position in which a given object could be inserted
 *        without changing the ordering.
 *
 * @return An index to the first object greater than obj, or array size
 *         if no objects are greater than obj.
 */
IMSize          im_object_array_upper_bound_with_data   (const IMObjectArray    *array,
                                                         IMPointer               obj,
                                                         IMCompareDataFunc       compare_func,
                                                         IMPointer               user_data);
/**
 * @brief Traverse all objects in an IMObjectArray object by calling specific
 *        function with user_data.
 */
void            im_object_array_foreach         (const IMObjectArray    *array,
                                                 IMFunc                  func,
                                                 IMPointer               user_data);

IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
